import asyncio
import uuid
from pathlib import Path
from typing import Optional
import aiofiles
import time
import json


class StorageManager:
    """文件存储管理器"""
    
    def __init__(self, base_path: Path, ttl: int = 3600):
        self.base_path = Path(base_path)
        self.ttl = ttl
        self.metadata_file = self.base_path / "metadata.json"
        
        # 确保存储目录存在
        self.base_path.mkdir(parents=True, exist_ok=True)
        
        # 初始化元数据
        self._metadata = self._load_metadata()
    
    def _load_metadata(self) -> dict:
        """加载文件元数据"""
        if self.metadata_file.exists():
            try:
                with open(self.metadata_file, 'r') as f:
                    return json.load(f)
            except:
                pass
        return {}
    
    def _save_metadata(self):
        """保存文件元数据"""
        with open(self.metadata_file, 'w') as f:
            json.dump(self._metadata, f, indent=2)
    
    async def store_file(self, content: bytes, filename: str, content_type: str = "application/octet-stream") -> str:
        """存储文件并返回文件ID"""
        file_id = str(uuid.uuid4())
        file_path = self.base_path / f"{file_id}_{filename}"
        
        # 存储文件
        async with aiofiles.open(file_path, 'wb') as f:
            await f.write(content)
        
        # 保存元数据
        self._metadata[file_id] = {
            "filename": filename,
            "file_path": str(file_path),
            "content_type": content_type,
            "size": len(content),
            "created_at": time.time(),
            "expires_at": time.time() + self.ttl
        }
        self._save_metadata()
        
        return file_id
    
    async def get_file(self, file_id: str) -> Optional[tuple[bytes, dict]]:
        """根据文件ID获取文件内容和元数据"""
        if file_id not in self._metadata:
            return None
        
        metadata = self._metadata[file_id]
        
        # 检查是否过期
        if time.time() > metadata["expires_at"]:
            await self.delete_file(file_id)
            return None
        
        file_path = Path(metadata["file_path"])
        if not file_path.exists():
            # 文件不存在，清理元数据
            del self._metadata[file_id]
            self._save_metadata()
            return None
        
        try:
            async with aiofiles.open(file_path, 'rb') as f:
                content = await f.read()
            return content, metadata
        except:
            return None
    
    async def delete_file(self, file_id: str) -> bool:
        """删除文件"""
        if file_id not in self._metadata:
            return False
        
        metadata = self._metadata[file_id]
        file_path = Path(metadata["file_path"])
        
        # 删除文件
        if file_path.exists():
            file_path.unlink()
        
        # 删除元数据
        del self._metadata[file_id]
        self._save_metadata()
        
        return True
    
    async def cleanup_expired(self):
        """清理过期文件"""
        current_time = time.time()
        expired_files = []
        
        for file_id, metadata in self._metadata.items():
            if current_time > metadata["expires_at"]:
                expired_files.append(file_id)
        
        for file_id in expired_files:
            await self.delete_file(file_id)
        
        return len(expired_files)
    
    def get_file_info(self, file_id: str) -> Optional[dict]:
        """获取文件信息"""
        if file_id not in self._metadata:
            return None
        
        metadata = self._metadata[file_id].copy()
        
        # 检查是否过期
        if time.time() > metadata["expires_at"]:
            return None
        
        return metadata